package com.nxp.nfc_demo.reader;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Locale;
import java.util.concurrent.TimeoutException;

import android.R.integer;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.hardware.Camera.Size;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.nxp.NFC2COM.R;
import com.nxp.nfc_demo.activities.MainActivity;
import com.nxp.nfc_demo.activities.RegisterConfigActivity;
import com.nxp.nfc_demo.activities.RegisterSessionActivity;
import com.nxp.nfc_demo.activities.VersionInfoActivity;
import com.nxp.nfc_demo.crypto.CRC32Calculator;
import com.nxp.nfc_demo.exceptions.DemoNotSupportedException;
import com.nxp.nfc_demo.fragments.LedFragment;
import com.nxp.nfc_demo.fragments.NdefFragment;
import com.nxp.nfc_demo.fragments.SpeedTestFragment;
import com.nxp.nfc_demo.fragments.WebViewFragment;
import com.nxp.nfc_demo.reader.I2C_Enabled_Commands.CR_Offset;
import com.nxp.nfc_demo.reader.I2C_Enabled_Commands.NC_Reg_Func;
import com.nxp.nfc_demo.reader.I2C_Enabled_Commands.NS_Reg_Func;
import com.nxp.nfc_demo.reader.I2C_Enabled_Commands.R_W_Methods;
import com.nxp.nfc_demo.reader.I2C_Enabled_Commands.SR_Offset;
import com.nxp.nfc_demo.reader.Ntag_Get_Version.Prod;

/**
 * Class for the different Demos
 * 
 * @author NXP67729
 * 
 */
public class Ntag_I2C_Demo {
	I2C_Enabled_Commands reader;
	Activity main;
	Tag tag;
	String answer;
	Boolean ifwrite;//if need to write data to tag
	byte[] mbuffer;
	int mLen;
	public Handler mHandler1;
	protected final static String DATA_KEY = "uartnfc_data2233";
	protected final static String DATA_LENKEY = "DATALEN123654";
	
	// Led Demo reference that allows the MainActivity to stop the thread when a
	// new tab is opened
	LedTask lTask;
	SRAMSpeedtestTask sramspeedtask;
	EEPROMSpeedtestTask eepromspeedtask;
	WriteEmptyNdefTask emptyNdeftask;
	public void sendNFCProximityEvent(Tag tag) {
		SpeedTestFragment.sendNFCProximityEvent(tag);
	}
	/**
	 * Constructor
	 * 
	 * @param tag
	 *            Tag with which the Demos should be performed
	 * @param main
	 *            MainActivity
	 */
	public Ntag_I2C_Demo(Tag tag, final Activity main) {
		try {
			if (tag == null) {
				this.main = null;
				this.tag = null;
				return;

			}
			this.main = main;
			this.tag = tag;

			reader = I2C_Enabled_Commands.get(tag);
			
			mHandler1 = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					//displayData(read, msg);
					//mScrollView.fullScroll(View.FOCUS_DOWN);
					Bundle bundle = msg.getData();
					mbuffer = bundle.getByteArray(DATA_KEY);
					mLen = bundle.getInt(DATA_LENKEY);
					ifwrite = true;
					super.handleMessage(msg); 
				}
			};
			

			if (reader == null) {
				new AlertDialog.Builder(main)
						.setMessage(
								"The Tag could not be identified or this NFC device does not support the NFC Forum commands needed to access this tag")
						.setTitle("Communication failed")
						.setPositiveButton("OK",
								new DialogInterface.OnClickListener() {
									@Override
									public void onClick(DialogInterface dialog,
											int which) {

									}
								}).show();
			} else {
				reader.connect();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * Checks if the tag is still connected
	 * 
	 * @return Boolean indicating tag connection
	 * 
	 */
	public boolean isConnected() {
		return reader.isConnected();
	}

	public void FinishAllTasks() {
		//LEDFinish();
		SRAMSpeedFinish();
		//EEPROMSpeedFinish();
		//WriteEmptyNdefFinish();
	}

	/**
	 * Checks if the demo is ready to be executed
	 * 
	 * @return Boolean indicating demo readiness
	 * 
	 */
	public boolean isReady() {
		if (tag != null && reader != null)
			return true;
		else
			return false;
	}

	public Prod getProduct() throws IOException {
		return reader.getProduct();
	}

	public void getBoardVersion() throws IOException, FormatException,
			DemoNotSupportedException {

		byte[] DataTx = new byte[reader.getSRAMSize()];
		byte[] DataRx = new byte[reader.getSRAMSize()];

		DataTx[reader.getSRAMSize() - 4] = 'V';

		if (!((reader.getSessionRegister(SR_Offset.NC_REG) & NC_Reg_Func.PTHRU_ON_OFF
				.getValue()) == NC_Reg_Func.PTHRU_ON_OFF.getValue())) {
			VersionInfoActivity.setBoardVersion("No Board attached");
			VersionInfoActivity.setBoardFWVersion("No Board attached");
			return;
		}

		try {
			reader.waitforI2Cread(100);
		} catch (TimeoutException e1) {
			e1.printStackTrace();
			
			VersionInfoActivity.setBoardVersion("No Board attached");
			VersionInfoActivity.setBoardFWVersion("No Board attached");
			return;
		}

		reader.writeSRAMBlock(DataTx);

		for (int i = 0; i < 300; i++) {
			if (((reader.getSessionRegister(SR_Offset.NS_REG) & NS_Reg_Func.SRAM_RF_READY
					.getValue()) == NS_Reg_Func.SRAM_RF_READY.getValue())) {
				break;
			}
			try {
				Thread.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		if (!((reader.getSessionRegister(SR_Offset.NS_REG) & NS_Reg_Func.SRAM_RF_READY
				.getValue()) == NS_Reg_Func.SRAM_RF_READY.getValue())) {
			VersionInfoActivity.setBoardVersion("1.0");
			VersionInfoActivity.setBoardFWVersion("1.0");
			return;
		}

		DataRx = reader.readSRAMBlock();

		String Board_Version;
		String Board_FW_Version;
		// Check if Data was send, else it is a ExplorerBoard FW
		if (DataRx[12] == 0) {
			String Version = Integer.toHexString((DataRx[63] >> 4)
					& (byte) 0x0F)
					+ "." + Integer.toHexString(DataRx[63] & (byte) 0x0F);
			Board_Version = Version;
			Board_FW_Version = Version;
		} else {
			Board_Version = new String(DataRx, 12, 3);
			Board_FW_Version = new String(DataRx, 28, 3);
		}

		VersionInfoActivity.setBoardVersion(Board_Version);
		VersionInfoActivity.setBoardFWVersion(Board_FW_Version);
	}

	/**
	 * Resets the tag to its delivery values
	 * 
	 * @return Boolean indicating success or error
	 * 
	 */
	public boolean resetTag() {
		boolean success = true;

		try {
			reader.writeDeliveryNdef();
		} catch (Exception e) {
			success = false;
			e.printStackTrace();
		}

		return success;
	}

	/**
	 * Builds a String array for the Registers
	 * 
	 * @param register
	 *            Byte Array of the Registers
	 * @return String Array
	 * @throws IOException
	 * @throws FormatException
	 */
	private Ntag_I2C_Registers getRegister_Settings(byte[] register)
			throws IOException, FormatException {
		Ntag_I2C_Registers answer = new Ntag_I2C_Registers();

		Ntag_Get_Version.Prod prod = reader.getProduct();

		if (!prod.equals(Ntag_Get_Version.Prod.Unknown)) {
			if (prod.equals(Ntag_Get_Version.Prod.NTAG_I2C_1k))
				answer.Manufacture = main
						.getString(R.string.ic_prod_ntagi2c_1k);
			else if (prod.equals(Ntag_Get_Version.Prod.NTAG_I2C_2k))
				answer.Manufacture = main
						.getString(R.string.ic_prod_ntagi2c_2k);

			answer.Mem_size = prod.getMemsize();
		} else {
			answer.Manufacture = "";
			answer.Mem_size = 0;
		}

		byte NC_Reg = register[SR_Offset.NC_REG.getValue()];

		// check I2C_RST_ON_OFF
		if ((NC_Reg & NC_Reg_Func.I2C_RST_ON_OFF.getValue()) == NC_Reg_Func.I2C_RST_ON_OFF
				.getValue())
			answer.I2C_RST_ON_OFF = true;
		else
			answer.I2C_RST_ON_OFF = false;

		// check FD_OFF
		byte tmpReg = (byte) (NC_Reg & NC_Reg_Func.FD_OFF.getValue());
		if (tmpReg == (0x30))
			answer.FD_OFF = main.getString(R.string.FD_OFF_ON_11);
		if (tmpReg == (0x20))
			answer.FD_OFF = main.getString(R.string.FD_OFF_ON_10);
		if (tmpReg == (0x10))
			answer.FD_OFF = main.getString(R.string.FD_OFF_ON_01);
		if (tmpReg == (0x00))
			answer.FD_OFF = main.getString(R.string.FD_OFF_ON_00);

		// check FD_ON
		tmpReg = (byte) (NC_Reg & NC_Reg_Func.FD_ON.getValue());
		if (tmpReg == (0x0c))
			answer.FD_ON = main.getString(R.string.FD_OFF_ON_11);
		if (tmpReg == (0x08))
			answer.FD_ON = main.getString(R.string.FD_OFF_ON_10);
		if (tmpReg == (0x04))
			answer.FD_ON = main.getString(R.string.FD_OFF_ON_01);
		if (tmpReg == (0x00))
			answer.FD_ON = main.getString(R.string.FD_OFF_ON_00);

		// Last NDEF Page
		answer.LAST_NDEF_PAGE = (0x00000FF & register[SR_Offset.LAST_NDEF_PAGE
				.getValue()]);

		byte NS_Reg = register[SR_Offset.NS_REG.getValue()];

		// check NDEF_DATA_READ
		if ((NS_Reg & NS_Reg_Func.NDEF_DATA_READ.getValue()) == NS_Reg_Func.NDEF_DATA_READ
				.getValue())
			answer.NDEF_DATA_READ = true;
		else
			answer.NDEF_DATA_READ = false;

		// check RF_FIELD
		if ((NS_Reg & NS_Reg_Func.RF_FIELD_PRESENT.getValue()) == NS_Reg_Func.RF_FIELD_PRESENT
				.getValue())
			answer.RF_FIELD_PRESENT = true;
		else
			answer.RF_FIELD_PRESENT = false;

		// check PTHRU_ON_OFF
		if ((NC_Reg & (byte) NC_Reg_Func.PTHRU_ON_OFF.getValue()) == NC_Reg_Func.PTHRU_ON_OFF
				.getValue())
			answer.PTHRU_ON_OFF = true;
		else
			answer.PTHRU_ON_OFF = false;

		// check I2C_LOCKED
		if ((NS_Reg & NS_Reg_Func.I2C_LOCKED.getValue()) == NS_Reg_Func.I2C_LOCKED
				.getValue())
			answer.I2C_LOCKED = true;
		else
			answer.I2C_LOCKED = false;

		// check RF_LOCK
		if ((NS_Reg & NS_Reg_Func.RF_LOCKED.getValue()) == NS_Reg_Func.RF_LOCKED
				.getValue())
			answer.RF_LOCKED = true;
		else
			answer.RF_LOCKED = false;
		;

		// check check SRAM_I2C_Ready
		if ((NS_Reg & NS_Reg_Func.SRAM_I2C_READY.getValue()) == NS_Reg_Func.SRAM_I2C_READY
				.getValue())
			answer.SRAM_I2C_READY = true;
		else
			answer.SRAM_I2C_READY = false;

		// check SRAM_RF_READY
		tmpReg = (byte) (NS_Reg & NS_Reg_Func.SRAM_RF_READY.getValue());
		if ((NS_Reg & NS_Reg_Func.SRAM_RF_READY.getValue()) == NS_Reg_Func.SRAM_RF_READY
				.getValue())
			answer.SRAM_RF_READY = true;
		else
			answer.SRAM_RF_READY = false;

		// check PTHRU_DIR
		tmpReg = (byte) (NC_Reg & (byte) 0x01);
		if (tmpReg == (0x01))
			answer.PTHRU_DIR = true;
		else
			answer.PTHRU_DIR = false;

		// SM_Reg
		answer.SM_Reg = (0x00000FF & register[SR_Offset.SM_REG.getValue()]);

		// WD_LS_Reg
		answer.WD_LS_Reg = (0x00000FF & register[SR_Offset.WDT_LS.getValue()]);

		// WD_MS_Reg
		answer.WD_MS_Reg = (0x00000FF & register[SR_Offset.WDT_MS.getValue()]);

		// check SRAM_MIRROR_ON_OFF
		if ((NC_Reg & NC_Reg_Func.SRAM_MIRROR_ON_OFF.getValue()) == NC_Reg_Func.SRAM_MIRROR_ON_OFF
				.getValue())
			answer.SRAM_MIRROR_ON_OFF = true;
		else
			answer.SRAM_MIRROR_ON_OFF = false;

		// I2C_CLOCK_STR
		if (register[SR_Offset.I2C_CLOCK_STR.getValue()] == 1)
			answer.I2C_CLOCK_STR = true;
		else
			answer.I2C_CLOCK_STR = false;

		// read NDEF Message
		try {
			NdefMessage message = reader.readNDEF();
			String NDEFText = new String(message.getRecords()[0].getPayload(),
					"US-ASCII");
			NDEFText = NDEFText.subSequence(3, NDEFText.length()).toString();
			answer.NDEF_Message = NDEFText;
		} catch (Exception e) {
			answer.NDEF_Message = main.getString(R.string.No_NDEF);
		}

		return answer;
	}

	public void readSessionRegisters() throws DemoNotSupportedException {

		try {
			byte[] sessionRegisters = reader.getSessionRegisters();
			Ntag_I2C_Registers answer = getRegister_Settings(sessionRegisters);
			RegisterSessionActivity.SetAnswer(answer, main);

			Toast.makeText(main, "read tag successfully done",
					Toast.LENGTH_LONG).show();
		} catch (DemoNotSupportedException e) {
			throw e;
		}

		catch (Exception e) {
			Toast.makeText(main, "read tag failed", Toast.LENGTH_LONG).show();
		}
	}

	/**
	 * Reads/writes Config
	 * 
	 * @throws DemoNotSupportedException
	 * 
	 * @throws IOException
	 * @throws FormatException
	 */
	public void readWriteConfigRegister() throws DemoNotSupportedException {
		// Check if the operation is read or write
		if (RegisterConfigActivity.isWriteChosen() == true) {
			try {
				byte NC_Reg = (byte) RegisterConfigActivity.getNC_Reg();
				byte LD_Reg = (byte) RegisterConfigActivity.getLD_Reg();
				byte SM_Reg = (byte) RegisterConfigActivity.getSM_Reg();
				byte WD_LS_Reg = (byte) RegisterConfigActivity.getWD_LS_Reg();
				byte WD_MS_Reg = (byte) RegisterConfigActivity.getWD_MS_Reg();
				byte I2C_CLOCK_STR = (byte) RegisterConfigActivity
						.getI2C_CLOCK_STR();
				reader.writeConfigRegisters(NC_Reg, LD_Reg, SM_Reg, WD_LS_Reg,
						WD_MS_Reg, I2C_CLOCK_STR);

				Toast.makeText(main, "write tag successfully done",
						Toast.LENGTH_LONG).show();
			} catch (Exception e) {
				Toast.makeText(main, "write tag failed", Toast.LENGTH_LONG)
						.show();
			}
		} // END if get chosen
		else {
			try {
				byte[] configRegisters = reader.getConfigRegisters();

				Ntag_I2C_Registers answer = getRegister_Settings(configRegisters);
				RegisterConfigActivity.setAnswer(answer, main);
				RegisterConfigActivity
						.setNC_Reg(configRegisters[CR_Offset.NC_REG.getValue()]);
				RegisterConfigActivity
						.setLD_Reg(configRegisters[CR_Offset.LAST_NDEF_PAGE
								.getValue()]);
				RegisterConfigActivity
						.setSM_Reg(configRegisters[CR_Offset.SM_REG.getValue()]);
				RegisterConfigActivity
						.setNS_Reg(configRegisters[CR_Offset.REG_LOCK
								.getValue()]);
				RegisterConfigActivity
						.setWD_LS_Reg(configRegisters[CR_Offset.WDT_LS
								.getValue()]);
				RegisterConfigActivity
						.setWD_MS_Reg(configRegisters[CR_Offset.WDT_MS
								.getValue()]);
				RegisterConfigActivity
						.setI2C_CLOCK_STR(configRegisters[CR_Offset.I2C_CLOCK_STR
								.getValue()]);

				Toast.makeText(main, "read tag successfully done",
						Toast.LENGTH_LONG).show();
			} catch (DemoNotSupportedException e) {
				throw e;
			} catch (Exception e) {
				Toast.makeText(main, "read tag failed", Toast.LENGTH_LONG)
						.show();
			}
		}
	}

	/**
	 * Reads the whole tag memory content
	 * 
	 * @return Boolean indicating success or error
	 */
	public byte[] readTagContent() {
		byte[] bytes = null;

		try {
			// The user memory and the first four pages are displayed
			int memSize = reader.getProduct().getMemsize() + 16;

			// Read all the pages using the fast read method
			bytes = reader.readEEPROM(0, memSize / reader.getBlockSize());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (FormatException e) {
			e.printStackTrace();
		}

		return bytes;
	}

	/**
	 * Resets the whole tag memory content (Memory to 00000...)
	 * 
	 * @return Boolean indicating success or error
	 */
	public boolean resetTagContent() {
		boolean success = true;

		try {
			byte[] d = new byte[reader.getProduct().getMemsize()];
			reader.writeEEPROM(d);
		} catch (IOException e) {
			success = false;
			e.printStackTrace();
		} catch (FormatException e) {
			success = false;
			e.printStackTrace();
		}

		return success;
	}

	/**
	 * Performs the LED Demo
	 */
	public void LED() throws IOException, FormatException {
		// Reset UI
		LedFragment.setAnswer(main.getResources().getString(R.string.readConf));
		LedFragment.setTemperatureC(0);
		LedFragment.setTemperatureF(0);
		LedFragment.setVoltage(0);

		// The demo is executed in a separate thread to let the GUI run
		lTask = new LedTask();
		lTask.execute();
	}

	private class LedTask extends AsyncTask<Void, Byte[], Void> {

		public Boolean exit = false;

		@Override
		protected Void doInBackground(Void... params) {
			byte[] DataTx = new byte[reader.getSRAMSize()];
			byte[] DataRx = new byte[reader.getSRAMSize()];
			byte[] Led;

			// We have to make sure that the Pass-Through mode is activated
			long RegTimeOutStart = System.currentTimeMillis();
			boolean RTest = false;

			try {
				do {

					if (reader.checkPTwritePossible()) {
						break;
					}

					long RegTimeOut = System.currentTimeMillis();
					RegTimeOut = RegTimeOut - RegTimeOutStart;
					RTest = (RegTimeOut < 5000);

				} while (RTest);

				// Do as long as no Exception is thrown
				while (true) {

					// Get the color to be transmitted
					Led = LedFragment.getOption().getBytes();

					// Write the color into the block to be transmitted to the
					// NTAG board
					DataTx[reader.getSRAMSize() - 4] = Led[0];
					DataTx[reader.getSRAMSize() - 3] = Led[1];

					// NDEF Scrolling activation
					DataTx[reader.getSRAMSize() - 9] = (byte) (LedFragment
							.getScrolling() ? 1 : 0);

					double tempC = LedFragment.getTemperatureC();
					double tempF = LedFragment.getTemperatureF();

					if (tempC > 0.0 && tempC < 75.0) {
						DecimalFormat df = new DecimalFormat("00.00");
						byte[] tempB = df.format(tempC).getBytes();

						// The '.' is omitted
						DataTx[reader.getSRAMSize() - 24] = tempB[0];
						DataTx[reader.getSRAMSize() - 23] = tempB[1];
						DataTx[reader.getSRAMSize() - 22] = tempB[3];
						DataTx[reader.getSRAMSize() - 21] = tempB[4];
					}

					if (tempF > 0.0 && tempF < 120.0) {
						DecimalFormat df = new DecimalFormat("000.00");
						byte[] tempB = df.format(tempF).getBytes();

						// The '.' is omitted
						DataTx[reader.getSRAMSize() - 19] = tempB[0];
						DataTx[reader.getSRAMSize() - 18] = tempB[1];
						DataTx[reader.getSRAMSize() - 17] = tempB[2];
						DataTx[reader.getSRAMSize() - 16] = tempB[4];
						DataTx[reader.getSRAMSize() - 15] = tempB[5];
					}

					double voltD = LedFragment.getVoltage();

					if (voltD > 0.0 && voltD < 5.0) {
						DecimalFormat df = new DecimalFormat("0.0");
						byte[] voltB = df.format(voltD).getBytes();

						// The '.' is omitted
						DataTx[reader.getSRAMSize() - 8] = voltB[0];
						DataTx[reader.getSRAMSize() - 7] = voltB[2];
					}
					
					// wait to prevent that a RF communication is
					// at the same time as �C I2C
					Thread.sleep(10);
					
					reader.waitforI2Cread(100);

					reader.writeSRAMBlock(DataTx);
					
					// wait to prevent that a RF communication is
					// at the same time as �C I2C
					Thread.sleep(10);

					reader.waitforI2Cwrite(100);

					DataRx = reader.readSRAMBlock();

					// Convert byte[] to Byte[]
					Byte[] bytes = new Byte[DataRx.length];
					for (int i = 0; i < DataRx.length; i++) {
						bytes[i] = Byte.valueOf(DataRx[i]);
					}

					if (exit) {
						// switch off the LED on the �C before terminating

						DataTx[reader.getSRAMSize() - 4] = Led[0];
						DataTx[reader.getSRAMSize() - 3] = '0';

						// wait to prevent that a RF communication is
						// at the same time as �C I2C
						Thread.sleep(10);
						reader.waitforI2Cread(100);
						
						reader.writeSRAMBlock(DataTx);
						
						// wait to prevent that a RF communication is
						// at the same time as �C I2C
						Thread.sleep(10);
						reader.waitforI2Cwrite(100);

						DataRx = reader.readSRAMBlock();

						cancel(true);
						return null;
					}

					// Write the result to the UI thread
					publishProgress(bytes);

				}
			} catch (FormatException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}

			return null;
		}

		@Override
		protected void onProgressUpdate(Byte[]... bytes) {

			LedFragment.setButton(bytes[0][reader.getSRAMSize() - 2]);

			int Temp = 0;

			// Adding first "Byte"
			Temp = ((bytes[0][reader.getSRAMSize() - 5] >> 5) & 0x00000007);

			// Adding second Byte
			Temp |= ((bytes[0][reader.getSRAMSize() - 6] << 3) & 0x000007F8);

			// Voltage
			int Voltage = 0;
			Voltage = ((bytes[0][reader.getSRAMSize() - 7] << 8) & 0xff00)
					+ (bytes[0][reader.getSRAMSize() - 8] & 0x00ff);

			// if Temp is 0 no Temp sensor is on the �C
			if (Temp != 0) {
				// Set the values on the screen
				LedFragment.setAnswer("Temperature: " + calcTempCelsius(Temp)
						+ " �C / " + calcTempFarenheit(Temp) + " �F"
						+ "\nEnergy Harvesting Voltage: "
						+ calcVoltage(Voltage));
			} else {
				LedFragment.setAnswer("Temperature: " + "Not available"
						+ "\nEnergy Harvesting Voltage: "
						+ calcVoltage(Voltage));
				LedFragment.setTemperatureC(0);
				LedFragment.setTemperatureF(0);
			}

			byte Version = bytes[0][reader.getSRAMSize() - 1];
			if (Version > 0) {
				int uppVersion = (Version >> 4) & 0x0f;
				int lowVersion = Version & 0x0f;

				MainActivity.boardFirmwareVersion = String.valueOf(uppVersion)
						+ "." + String.valueOf(lowVersion);
			} else
				MainActivity.boardFirmwareVersion = "1.0";
		}

	}

	/**
	 * Stops the LED Demo
	 */
	public void LEDFinish() {
		if (lTask != null && !lTask.isCancelled()) {
			lTask.exit = true;
			try {
				lTask.get();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			lTask = null;
		}
	}

	/**
	 * Performs the NDEF Demo
	 */
	public void NDEF() throws IOException {
		// Check if the operation is read or write
		if (NdefFragment.isWriteChosen() == true) {
			// NDEF Message to write in the tag
			NdefMessage msg = null;

			// Get the selected NDEF type since the creation of the NDEF Msg
			// will vary depending on the type
			if (NdefFragment.getNdefType().equalsIgnoreCase(
					main.getResources().getString(R.string.radio_text))) {
				msg = createNdefTextMessage("0000000"+NdefFragment.getText()+"0E000000");//ADDED BY PETER
			} else if (NdefFragment.getNdefType().equalsIgnoreCase(
					main.getResources().getString(R.string.radio_uri))) {
				msg = createNdefUriMessage(NdefFragment.getText());
			} else if (NdefFragment.getNdefType().equalsIgnoreCase(
					main.getResources().getString(R.string.radio_btpair))) {
				msg = createNdefBSSPMessage();
			}

			try {
				NDEFWrite(msg);

				// Inform the MCU about the new NDEF message that has been
				// stored
				// N: reference for NDEF
				if (!(reader instanceof MinimalNtag_I2C_Commands) & reader.checkPTwritePossible()) {
					byte[] Data = new byte[64];
					Data[reader.getSRAMSize() - 4] = 'N';
					reader.writeSRAMBlock(Data);
				}
				Toast.makeText(main, "write tag successfully done",
						Toast.LENGTH_LONG).show();
			} catch (Exception e) {
				Toast.makeText(main, "write tag failed", Toast.LENGTH_LONG)
						.show();
			}
		} else {
			try {
				// Get the message Type
				NdefMessage msg = reader.readNDEF();

				// Get the message type in order to deal with it appropriately
				String type = getNdefMessageType(msg);

				String Message = "";
				if (type.equals(main.getResources().getString(
						R.string.radio_text)))
					{ Message = NDEFReadText(msg); }
				else if (type.equals(main.getResources().getString(
						R.string.radio_uri)))
					{ Message = NDEFReadURI(msg); }
				else if (type.equals(main.getResources().getString(
						R.string.radio_btpair)))
					{ Message = NDEFReadBSSP(msg); }
				else 
					{ Message = "no parser for this NDEF message type in this demo"; }

				// Put the message content on the screen
				NdefFragment.setNdefType(type);
				NdefFragment.setNdefMessage(Message);

				// showResultDialog("read tag successfully done");
				Toast.makeText(main, "read tag successfully done",
						Toast.LENGTH_LONG).show();
			} catch (Exception e) {
				// Reset the content that is on the edittext
				NdefFragment.setNdefMessage("");

				// showResultDialog("read tag failed");
				Toast.makeText(main, main.getString(R.string.No_NDEF),
						Toast.LENGTH_LONG).show();
			}
		}
	}

	/**
	 * Performs the SRAM Speedtest
	 * 
	 * @throws IOException
	 * @throws FormatException
	 */
	public void SRAMSpeedtest() throws IOException, FormatException {
		// During the SRAM test we write 64 bytes in the memory space dedicated
		// for it
		// S: reference for the SpeedTest

		sramspeedtask = new SRAMSpeedtestTask();
		sramspeedtask.execute();

	}

public boolean SendData(byte [] datastring,int len)
{
	byte[] Data;
	byte[] temp;
	int chMultiplier;
				SpeedTestFragment.setDatarateCallback("begin to write");
				long RegTimeOutStart = System.currentTimeMillis();
			try {
				while (true) {
					if (reader.checkPTwritePossible()) {
						//publishProgress("Pass Through Mode is ON");
						SpeedTestFragment.setDatarateCallback("Pass Through Mode is ON");
						break;
					} else {
						//publishProgress("Pass Through Mode is OFF");
						 SpeedTestFragment.setDatarateCallback("Pass Through Mode is OFF");
					}
					if (((System.currentTimeMillis() - RegTimeOutStart) > 5000)) {
						//publishProgress("Pass Through Mode was OFF, ERROR time out");
						SpeedTestFragment.setDatarateCallback("Pass Through Mode was OFF, ERROR time out");
						 
						return false;
					}
				}
				
				SpeedTestFragment.setDatarateCallback("Step 1");
				
				if(datastring==null)//for test
				{
					
				
				
			    int datalen = 100;
			                    //
			                
				// ///////////////
				// send CMD quest send data to UART
				// ///////////////
				Data = new byte[64];
				Data[0] = (byte) 0xfe;
				Data[1] = (byte) 0xfe;
				Data[2] = (byte) 0xfe;
				Data[3] = (byte) 0xfe;
				Data[4] = (byte)0x3;//type: quest to send
				Data[5] = (byte) ((0xff000000 & datalen) >> 24);//最高位;
				Data[6] = (byte) ((0xff0000 & datalen) >> 16);
				Data[7] = (byte) ((0xff00 & datalen) >> 8);
				Data[8] = (byte) (0xff & datalen);			
				
				//reader.writeSRAMBlock(Data);
				temp =null;
				try {
					   while(true)
					   {
							try {
								reader.writeSRAMBlock(Data);
							} catch (Exception e) {
								// TODO: handle exception
								reader.close();
								reader.connect();
								continue;
							}
							
							try
							{
							 reader.waitforI2Cwrite(200);
							}catch (TimeoutException e)
							{
							           // e.printStackTrace();
								//SpeedTestFragment.setDatarateCallback("Time out2");
							 //return false;
								continue;
							 
							}
							break;
						}
						// ///////////////
						// Read the response Data (I2C --RF)
						// /////////////// 					
						while(true)
						{
							try {
								temp = reader.readSRAMBlock();
								
							} catch (Exception e) {
							 reader.close();
							 reader.connect();
							 continue;
							}
							break;
						}
						
						
						
						
						if((temp[1]==0xfe)&&(temp[2]==0xfe)&&(temp[3]==0xfe))
						{
						    if(temp[9]==0xe7)//send data
						    {
							
						    }
						    else// if(temp[9]==0xe9)
						    {
						    	SpeedTestFragment.setDatarateCallback("Uart busy1");
						    	return false;
						    }
						}
  
						// ///////////////
						// Begin to transmit Data (RF -> I2C)
						// ///////////////
					
						// create array
						chMultiplier = (int) (datalen/64) ;
						if((chMultiplier *64) < datalen)
						{
						  chMultiplier = chMultiplier+1;
						}
						Data = new byte[ chMultiplier *64];
						byte j=0;
						for(int i=0;i<datalen;i++)
						{ 
							Data[i] = j;
							j++;
							if(j>255)
							  {
							  	j=0;
							  }
							  
					   }
			
				// adding the finish text
			        Data[datalen-3]=0x45;
					 Data[datalen-2]=0x4e;
					 Data[datalen - 1]=0x44;

					for (int i = 0; i < chMultiplier; i++) 
					{
						 while(true)
						 {
							try {
								 reader.writeSRAMBlock(Data);
							    }
							 catch (Exception e) {
									// Inform the user about the error
									//String Message = "Phone sends too fast or Tag was lost, try Polling mode";
									//publishProgress(Message);
									//cancel(true);
									//return null;
							     reader.close();
							     reader.connect();
							     continue;
							     
								}
							

								try{
								    reader.waitforI2Cread(50);
								}catch (TimeoutException e)
									{
									 // e.printStackTrace();
									 continue;
									}
								
								break;
								
							 }
						// Publish the Progress
							SpeedTestFragment.displaynomove(((i + 1) * reader.SRAMSize)
									+ " Bytes written");

						if (Data.length > reader.getSRAMSize())
							Data = Arrays.copyOfRange(Data, reader.getSRAMSize(),
									Data.length);
									
				     }	
				
				} catch (Exception e) {
					// TODO: handle exception
					e.printStackTrace();
					SpeedTestFragment.setDatarateCallback("Uart busy2");
			    	return false;
					
				}
				
				}
				else {//true send data here
					
					len = len+16;// 添加帧头帧尾等信息后的长度
							Data = new byte[64];
							Data[0] = (byte) 0xfe;
							Data[1] = (byte) 0xfe;
							Data[2] = (byte) 0xfe;
							Data[3] = (byte) 0xfe;
							Data[4] = (byte)0x3;//type: quest to send
							Data[5] = (byte) ((0xff000000 & len) >> 24);//最高位;
							Data[6] = (byte) ((0xff0000 & len) >> 16);
							Data[7] = (byte) ((0xff00 & len) >> 8);
							Data[8] = (byte) (0xff & len);			
						 
							
							 while(true)
							 {
								//reader.writeSRAMBlock(Data);
								try {
								      reader.writeSRAMBlock(Data);
							       }
							       catch (Exception e) {
								     reader.close();
								     reader.connect();
								     continue;
							           }
								
								// ///////////////
								// Read the response Data (I2C --RF)
								// /////////////// 						
								try
									{
									 reader.waitforI2Cwrite(300);
									}catch (TimeoutException e)
									{
									           // e.printStackTrace();
									 continue;
									 
									}
								   break;
						      }
							 
							  while(true)
							  {
								 try {
									   temp = reader.readSRAMBlock();
									 } catch (Exception e) {
										// TODO: handle exception
									     reader.close();
									     reader.connect();
									     continue;
									  }
								 break;
							   }
							
								if((temp[1]==0xfe)&&(temp[2]==0xfe)&&(temp[3]==0xfe))
								{
								    if(temp[9]==0xe7)//send data
								    {
									
								    }
								    else// if(temp[9]==0xe9)
								    {
								    	SpeedTestFragment.setDatarateCallback("Uart busy3");
								    	return false;
								    }
								}
							    
							// ///////////////
							// Begin to transmit Data (RF -> I2C)
							// ///////////////
						
							// create array
							chMultiplier = (int) (len/64) ;
							if((chMultiplier *64) < len)
							{
							  chMultiplier = chMultiplier+1;
							}
							Data = new byte[ chMultiplier *64];
							
							Data[0]=(byte) 0xfe;
							Data[1]=(byte) 0xfe;
							Data[2]=(byte) 0xfe;
							Data[3]=(byte) 0xfe;
							Data[4]=0x1;
							Data[5] = (byte) ((0xff000000 & len) >> 24);//最高位;
							Data[6] = (byte) ((0xff0000 & len) >> 16);
							Data[7] = (byte) ((0xff00 & len) >> 8);
							Data[8] = (byte) (0xff & len);	
							int j=0;
							for(int i=9;i<(len-7);i++)
							{ 
								Data[i] = (byte)datastring[j];
								j++;
						    }
						
							// adding the finish text
						        Data[len-3]=0x45;
								Data[len-2]=0x4e;
								Data[len-1]=0x44;
								
								Data[len-7]=(byte)0xff;
						        Data[len-6]=(byte)0xff;
								Data[len-5]=(byte)0xff;
								Data[len-4]=(byte)0xff;
								         
						
							for (int i = 0; i < chMultiplier; i++) 
							{
								while(true)
								{
									try {
										reader.writeSRAMBlock(Data);
									    }
									    catch (Exception e) {
										     reader.close();
										     reader.connect();
										     continue;
									     
										}
									// cancle task if requested
							
									try{
									    reader.waitforI2Cread(50);
									   }catch (TimeoutException e)
										{
										 continue;
										}
								  break;
								}
								// Publish the Progress
								SpeedTestFragment.displaynomove(((i + 1) * reader.SRAMSize)
										+ " Bytes written");
								
								if (len > reader.getSRAMSize())
								{
									Data = Arrays.copyOfRange(Data, reader.getSRAMSize(),
											len);
								len = len-64;
								}
					
							 }	
							
							
							
					
				}
				
				
			} catch (Exception e) {
				// TODO: handle exception
				Log.e("NFC2COM", e.toString());
				SpeedTestFragment.setDatarateCallback("Send Error 4");
				return false;
			}
				
			    		        
	return true;	
}


public boolean ReceiveData(int len)
{
	int block;
	int lest;
	if(len>64)
	{
		block = len/64;
		if((block*64)<len)
		{
			block++;
		}
	}
	else {
      block =1;
	}
	
	
	long TimeOutStart = System.currentTimeMillis();
	long TimeOutend=0;
	
	while(block>0)
	{
		try
		{
			
			try
			{
			  reader.waitforI2Cwrite(100);
			}catch (TimeoutException e)
			{
	           // e.printStackTrace();
				//SpeedTestFragment.setDatarateCallback("Time out1");
				TimeOutend = System.currentTimeMillis();
				TimeOutend = TimeOutend - TimeOutStart;
	           continue;
	        }
			block --;  
			if(block ==0)
			{
				lest = len%64;
				byte[] inbuffer = new byte[lest];
				byte[] tesmp =reader.readSRAMBlock();
				for(int i=0;i<lest;i++)
				{
					inbuffer[i]=tesmp[i];
				}
				SpeedTestFragment.Display_bytes(inbuffer,64);
			}
			else {
				SpeedTestFragment.Display_bytes(reader.readSRAMBlock(),64);
			}
			
			 
			TimeOutStart = System.currentTimeMillis();
			
		}
		 catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FormatException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if(TimeOutend >5000)
		{
			return true;//time out
		}
		
	}
	
	return false;
}
	
	private class SRAMSpeedtestTask extends AsyncTask<Void, String, Void> {

		public Boolean exit = false;

		byte[] Data;
		int chMultiplier;
		R_W_Methods method;
		long Reader_Tag_time;
		long Tag_Reade_time;
		boolean isValidRxData = false;
		boolean isValidTxData = false;
		boolean isValidFirmware = false;

		@Override
		protected void onPreExecute() {
			SpeedTestFragment.setAnswer("onPreEecute");
/*
			// getting Block multiplier
			String blockMulti = SpeedTestFragment.getrf_ndef_value_charmulti();

			chMultiplier = 1;
			int chMultiLength = blockMulti.length();

			if (chMultiLength == 0) {
				chMultiplier = 1;
			} else {
				chMultiplier = Integer.parseInt(blockMulti);
			}
*/
			// get Read Method
		
				method = R_W_Methods.Fast_Mode;
			
				// The minimalNtag_I2C_Commands does not use the sector_select, so it cannot not access the registers
				if(reader instanceof MinimalNtag_I2C_Commands)
				{
					new AlertDialog.Builder(main)
					.setMessage(
							"This NFC device does not support the NFC Forum commands needed to use the polling mode")
					.setTitle("Command not supported")
					.setPositiveButton("OK",
							new DialogInterface.OnClickListener() {
								@Override
								public void onClick(
										DialogInterface dialog,
										int which) {
	
								}
							}).show();
					
					exit = true;
				}
			

		}

		@Override
		protected Void doInBackground(Void... params) {
			byte[] temp;
			int errcount=0;
			// cancle task if requested
					
			ifwrite = true;
			
		 
			
		//	try{
					
				// Modified reader.readSRAM() to also get update to the UI
				// -----
				byte[] response = new byte[0];
				//Thread.sleep(300);
			
				//for (int i = 0; i < chMultiplier; i++) 
				 while(true)
				 {
					 if (exit) {
							cancel(true);
							return null;
						}
					
					
				    if(ifwrite)//write
				    {
					ifwrite = false;
					//publishProgress("i want to write");
					/*
					Bundle bundle = new Bundle();
					bundle.putByteArray(DATA_KEY, "begin to write".getBytes());
					bundle.putBoolean(JUDGE_KEY, false);//send
					Message msg = new Message();
					msg.setData(bundle);
					MainActivity.mHandler.sendMessage(msg);
					     */
					SendData(mbuffer,mLen);
					mbuffer=null;
                            		       	
					
				    }
				    else  //read
				    {
				    try{
							try
							{
							  reader.waitforI2Cwrite(100);
							}catch (TimeoutException e)
							{
					           // e.printStackTrace();
								//SpeedTestFragment.setDatarateCallback("Time out1");
								
					         continue;
					        }
							temp =null;
							
							temp = reader.readSRAMBlock();
							
						
				    	}catch(Exception e)
				    	{   
				    		errcount++;
				    		if(errcount>10)//500
				    		{
				    			 
				    			SpeedTestFragment.setDatarateCallback("Time out5");
				    			break;
				    		}
					    		try {
									reader.close();
									reader.connect();
								} catch (Exception e2) {
									// TODO: handle exception
									break;
								}
				    		continue;
				    	}
				       errcount=0;
				    
							if(temp[4]==0x2)//Uart have data to send
							{
								//SpeedTestFragment.setDatarateCallback("got the data:");
								//get the length
								int getlen;
								
								  getlen = (int)temp[9]<<24;//最高位
								  getlen |= (int)temp[10]<<16;
								  getlen |= (int)temp[11]<<8;
								  getlen |= (int)temp[12];
								  SpeedTestFragment.setDatarateCallback("got data length:"+getlen);
								  
								 if(ReceiveData(getlen))
								 {
									 SpeedTestFragment.setDatarateCallback("Read time out");
								 }
								
							}
							else if(temp[4]==0x3)//Uart ready
							{
								 SpeedTestFragment.setDatarateCallback("Uart ready");
								ifwrite =true;
							}
				    }
					
					
				  }
				// -----

				// if a error is detected [reader.getSRAMSize() - 5] is set to
				// 0x01
			
					
		/*	}
			catch(Exception e) {
				// Inform the user about the error
			        
				 String Message = "Phone sends too fast or Tag was lost, try Polling mode";
				// publishProgress(Message);
				 e.printStackTrace();
				 
				   cancel(true);
				  return null;
			}
				*/
			 	
			
			 
		 	return null;
					
			
		}

		@Override
		protected void onProgressUpdate(String... progress) {
			SpeedTestFragment.setDatarateCallback(progress[0]);
		}

		@Override
		protected void onPostExecute(Void bla) {

			// ///////////////
			// Show Results
			// ///////////////
		}

	}

	/**
	 * Stops the SRAMSpeed Demo
	 */
	public void SRAMSpeedFinish() {
		if (sramspeedtask != null && !sramspeedtask.isCancelled()) {
			sramspeedtask.exit = true;
			try {
				sramspeedtask.get();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			sramspeedtask = null;
		}
	}

	/**
	 * Appends the CRC32 to the message transmitted during the SRAM SpeedTest
	 * 
	 * @param b
	 *            The content to be transmitted to the NTAGI2C board
	 * 
	 * @return Byte Array with the CRC32s embedded in it
	 */
	private byte[] appendCRC32(byte[] b) {
		byte[] temp = new byte[b.length - 4];
		System.arraycopy(b, 0, temp, 0, temp.length);
		byte[] crc = CRC32Calculator.CRC32(temp);
		System.arraycopy(crc, 0, b, b.length - crc.length, crc.length);

		return b;
	}

	/**
	 * Checks if the CRC32 value has been appended in the message
	 * 
	 * @param b
	 *            The whole message received from the board
	 * 
	 * @return boolean that indicates the presence of the CRC32
	 */
	private boolean isCRC32Appended(byte[] b) {
		for (int i = b.length - 4; i < b.length; i++) {
			if (b[i] != 0x00)
				return true;
		}

		return false;
	}

	/**
	 * Checks the received CRC32 value in the message received from the NTAG I2C
	 * board during the SRAM SpeedTest
	 * 
	 * @param b
	 *            The whole message received from the board
	 * 
	 * @return boolean with the result of the comparison between the CRC32
	 *         received and the CRC32 calculated
	 */
	private boolean isValidCRC32(byte[] b) {
		byte[] receivedCRC = { b[b.length - 4], b[b.length - 3],
				b[b.length - 2], b[b.length - 1] };

		byte[] temp = new byte[b.length - 4];
		System.arraycopy(b, 0, temp, 0, b.length - 4);

		byte[] calculatedCRC = CRC32Calculator.CRC32(temp);

		return Arrays.equals(receivedCRC, calculatedCRC);
	}

	/**
	 * Performs the EEPROM Speedtest
	 * 
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 * @throws FormatException
	 */
	public void EEPROMSpeedtest() throws UnsupportedEncodingException,
			IOException, FormatException {

		eepromspeedtask = new EEPROMSpeedtestTask();
		eepromspeedtask.execute();
	}

	private class EEPROMSpeedtestTask extends
			AsyncTask<Void, String, NdefMessage> {

		public Boolean exit = false;

		long writeTime = 0;
		long readTime = 0;

		NdefMessage send_message;
		int ndef_message_size;

		@Override
		protected void onPreExecute() {

			try {
				SpeedTestFragment.setAnswer("EEPROM Speedtest");
				String textCharMulti = SpeedTestFragment
						.getrf_ndef_value_charmulti();

				// getting text multiplier
				int chMultiplier = 1;
				int chMultiLength = textCharMulti.length();
				if (chMultiLength == 0) {
					chMultiplier = 1;
				} else {
					chMultiplier = Integer.parseInt(textCharMulti);
				}

				// building string

				String messageText = "";
				for (int i = 0; i < chMultiplier; i++) {
					messageText = messageText.concat(" ");
				}

				// check Memory Length
				Ntag_Get_Version.Prod prod = reader.getProduct();
				int max_Memsize = prod.getMemsize();

				// creating NDEF

				// NDEF is max Text length + 5 bytes
				send_message = createNdefMessage(messageText);
				ndef_message_size = (send_message.toByteArray().length + 5);

				// if NDEF is shorter as Memsize write_EEPROM else write an
				// error

				if (ndef_message_size < max_Memsize) {
					SpeedTestFragment
							.setDatarateCallback("writing in progress...");
					// Execute doInBackground
					return;
				} else {
					SpeedTestFragment.setAnswer("NDEF Message too Long");
					SpeedTestFragment
							.setDatarateCallback("NDEF Message length: "
									+ ndef_message_size
									+ "\n\rMaximum allowed: " + max_Memsize);

					cancel(true);
					return;
				}
			} catch (Exception e) {
				e.printStackTrace();
				SpeedTestFragment.setDatarateCallback("Error try again");
				cancel(true);
				return;
			}
		}

		@Override
		protected NdefMessage doInBackground(Void... params) {
			try {

				writeTime = System.currentTimeMillis();
				reader.writeNDEF(send_message);
				writeTime = System.currentTimeMillis() - writeTime;

				if (exit) {
					cancel(true);
					return null;
				}

				publishProgress("writing finished \nreading in progress...");
				// Execute Read test
				readTime = System.currentTimeMillis();
				NdefMessage message = reader.readNDEF();
				readTime = System.currentTimeMillis() - readTime;

				if (exit) {
					cancel(true);
					return null;
				}
				publishProgress("writing finished \nreading finished");
				return message;
			} catch (Exception e) {
				e.printStackTrace();
				publishProgress("Error while sending, try again");
				cancel(true);
				return null;
			}
		}

		@Override
		protected void onProgressUpdate(String... progress) {
			SpeedTestFragment.setDatarateCallback(progress[0]);
		}

		@Override
		protected void onPostExecute(NdefMessage message) {

			if (message == null) {
				Toast.makeText(main, "NDEF Read not supported",
						Toast.LENGTH_LONG).show();
				return;
			}

			// Note: Write bytes value might be bigger than the Write bytes
			// value. This is because during the read process we read the whole
			// page

			// writing result to GUI
			String Message = "Written bytes: " + ndef_message_size + "\n";
			Message = Message.concat("Speed ("
					+ ndef_message_size
					+ " B / "
					+ writeTime
					+ " ms): "
					+ String.format("%.0f", ndef_message_size
							/ (writeTime / 1000.0)) + " B/s\n");
			Message = Message.concat("Read bytes: "
					+ (message.toByteArray().length) + "\n");
			Message = Message.concat("Speed ("
					+ message.toByteArray().length
					+ " B / "
					+ readTime
					+ " ms): "
					+ String.format("%.0f", message.toByteArray().length
							/ (readTime / 1000.0)) + " B/s");

			SpeedTestFragment.setAnswer("Test finished");
			SpeedTestFragment.setDatarateCallback(Message);

			// Put an empty NDEF Message in the memory
			emptyNdeftask = new WriteEmptyNdefTask();
			emptyNdeftask.execute();
		}
	}

	/**
	 * Stops the EEPROMSpeed Demo
	 */
	public void EEPROMSpeedFinish() {
		if (eepromspeedtask != null && !eepromspeedtask.isCancelled()) {
			eepromspeedtask.exit = true;
			try {
				eepromspeedtask.get();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			eepromspeedtask = null;
		}
	}

	private class WriteEmptyNdefTask extends AsyncTask<Void, Void, Void> {

		@SuppressWarnings("unused")
		public Boolean exit = false;

		@Override
		protected Void doInBackground(Void... params) {
			try {

				reader.writeEmptyNdef();
			} catch (Exception e) {
				e.printStackTrace();
				cancel(true);
				return null;
			}
			return null;
		}

	}

	/**
	 * Stops the EEPROMSpeed Demo
	 */
	public void WriteEmptyNdefFinish() {
		if (emptyNdeftask != null && !emptyNdeftask.isCancelled()) {
			emptyNdeftask.exit = true;
			try {
				emptyNdeftask.get();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			emptyNdeftask = null;
		}
	}

	private NdefMessage creatNdefDefaultMessage()
			throws UnsupportedEncodingException {
		NdefRecord uri_record = NdefRecord
				.createUri("http://www.zlit.com.cn");
		String text = "NTAG I2C Demoboard LPC812";
		String lang = "en";
		byte[] textBytes = text.getBytes();
		byte[] langBytes = lang.getBytes("US-ASCII");
		int langLength = langBytes.length;
		int textLength = textBytes.length;
		byte[] payload = new byte[1 + langLength + textLength];
		payload[0] = (byte) langLength;
		System.arraycopy(langBytes, 0, payload, 1, langLength);
		System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength);
		NdefRecord text_record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
				NdefRecord.RTD_TEXT, new byte[0], payload);

		NdefRecord[] sp_records = { uri_record, text_record };
		NdefMessage sp_message = new NdefMessage(sp_records);

		NdefRecord sp_record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
				NdefRecord.RTD_SMART_POSTER, new byte[0],
				sp_message.toByteArray());

		NdefRecord aap_record = NdefRecord.createApplicationRecord(main
				.getPackageName());

		NdefRecord[] records = { sp_record, aap_record };
		NdefMessage message = new NdefMessage(records);
		return message;

	}

	/**
	 * Creates a NDEF Text Message
	 * 
	 * @param text
	 *            Text to write
	 * @return NDEF Message
	 * @throws UnsupportedEncodingException
	 */
	private NdefMessage createNdefTextMessage(String text)
			throws UnsupportedEncodingException {
		String lang = "en";
		byte[] textBytes = text.getBytes();
		byte[] langBytes = lang.getBytes("US-ASCII");
		int langLength = langBytes.length;
		int textLength = textBytes.length;
		byte[] payload = new byte[1 + langLength + textLength];
		payload[0] = (byte) langLength;
		System.arraycopy(langBytes, 0, payload, 1, langLength);
		System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength);

		NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
				NdefRecord.RTD_TEXT, new byte[0], payload);

		NdefRecord[] records = { record };
		NdefMessage message = new NdefMessage(records);

		return message;
	}

	/**
	 * Creates a NDEF Uri Message
	 * 
	 * @param uri
	 *            Uri to write
	 * @return NDEF Message
	 */
	private NdefMessage createNdefUriMessage(String uri) {
		NdefRecord record = NdefRecord.createUri(uri);

		NdefRecord[] records = { record };
		NdefMessage message = new NdefMessage(records);

		return message;
	}

	/**
	 * Creates a Bluetooth Secure Simple Pairing Message
	 * 
	 * @param mac
	 *            Bluetooth MAC Address to Write
	 * @return NDEF Message
	 */
	private NdefMessage createNdefBSSPMessage() {
		byte[] payloadHs = { 0x12, (byte) 0xD1, 0x02, 0x04, 0x61, 0x63, 0x01,
				0x01, 0x30, 0x00 };
		NdefRecord recordHs = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
				NdefRecord.RTD_HANDOVER_SELECT, new byte[0], payloadHs);

		byte[] deviceMAC = hexStringToByteArray(NdefFragment.getBtMac()
				.replaceAll(":", ""));
		byte[] deviceName = NdefFragment.getBtName().getBytes();
		byte[] deviceClass = hexStringToByteArray(NdefFragment.getBtClass()
				.replaceAll(":", ""));

		byte[] payloadBt = new byte[deviceMAC.length + deviceName.length
				+ deviceClass.length + 2 + 4];

		// Payload Size
		payloadBt[0] = (byte) payloadBt.length;

		System.arraycopy(deviceMAC, 0, payloadBt, 2, deviceMAC.length);

		payloadBt[8] = (byte) (deviceName.length + 1);
		payloadBt[9] = 0x09; // Device Name identifier

		System.arraycopy(deviceName, 0, payloadBt, 10, deviceName.length);

		payloadBt[8 + deviceName.length + 2] = (byte) (deviceClass.length + 1);
		payloadBt[8 + deviceName.length + 3] = 0x0D; // Service Name identifier

		System.arraycopy(deviceClass, 0, payloadBt, 8 + deviceName.length + 4,
				deviceClass.length);

		NdefRecord recordBt = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
				"application/vnd.bluetooth.ep.oob".getBytes(), new byte[0],
				payloadBt);

		NdefRecord[] records = { recordHs, recordBt };
		NdefMessage message = new NdefMessage(records);

		return message;
	}

	public static byte[] hexStringToByteArray(String s) {
		int len = s.length();

		byte[] data = new byte[len / 2];
		for (int i = 0, j = (len - 2) / 2; i < len; i += 2, j--) {
			data[j] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character
					.digit(s.charAt(i + 1), 16));
		}
		return data;
	}

	/**
	 * Closes the Reader, Reads the NDEF Message via Android function and
	 * reconnects the Reader
	 * 
	 * @param msg
	 *            NDEF Message
	 * 
	 * @return Message Type
	 */
	private String getNdefMessageType(NdefMessage msg) {
		String type = "";

		NdefRecord records[] = msg.getRecords();

		if (records[0].getTnf() == NdefRecord.TNF_WELL_KNOWN) {
			if (Arrays.equals(records[0].getType(), NdefRecord.RTD_TEXT)) {
				type = main.getResources().getString(R.string.radio_text);
			} else if (Arrays.equals(records[0].getType(), NdefRecord.RTD_URI)) {
				type = main.getResources().getString(R.string.radio_uri);
			} else if (Arrays.equals(records[0].getType(),
					NdefRecord.RTD_HANDOVER_SELECT)) {
				// Now check that this is a BSSP Handover Select
				if (records[1].getTnf() == NdefRecord.TNF_MIME_MEDIA) {
					if (Arrays.equals(records[1].getType(),
							"application/vnd.bluetooth.ep.oob".getBytes())) {
						type = main.getResources().getString(
								R.string.radio_btpair);
					}
				}
			} else if (Arrays.equals(records[0].getType() , NdefRecord.RTD_SMART_POSTER))
				{ 
					type= "Smartposter Record"; 
					for (NdefRecord record : records)
					{
						//if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN & record.getType() == NdefRecord.)
					}
				}
		}

		return type;
	}

	/**
	 * Reads the NDEF Message Text
	 * 
	 * @param NDEF
	 *            Message
	 * 
	 * @return NDEF Message Text
	 * @throws UnsupportedEncodingException
	 */
	private String NDEFReadText(NdefMessage msg)
			throws UnsupportedEncodingException {
		String NDEFText = "";

		NDEFText = new String(msg.getRecords()[0].getPayload(), "US-ASCII");
		NDEFText = NDEFText.subSequence(3, NDEFText.length()).toString();

		return NDEFText;
	}

	/**
	 * Reads the NDEF Message URI
	 * 
	 * @param msg
	 *            Message
	 * 
	 * @return NDEF Message URI
	 * @throws UnsupportedEncodingException
	 */
	private String NDEFReadURI(NdefMessage msg)
			throws UnsupportedEncodingException {
		String NDEFText = "";

		NDEFText = new String(msg.getRecords()[0].getPayload(), 1,
				msg.getRecords()[0].getPayload().length - 1, "US-ASCII");
		NDEFText = getUriType(msg.getRecords()[0].getPayload()[0]).concat(
				NDEFText);

		return NDEFText;
	}

	/**
	 * Reads the NDEF Message Bluetooth Secure Simple Pairing
	 * 
	 * @param msg
	 *            Message
	 * 
	 * @return NDEF Message BSSP
	 * @throws UnsupportedEncodingException
	 */
	private String NDEFReadBSSP(NdefMessage msg)
			throws UnsupportedEncodingException {
		String NDEFText = "";

		byte[] payload = msg.getRecords()[1].getPayload();

		// First Field to parse: MAC Address;
		NDEFText = NDEFText.concat("MAC Address: ");
		for (int i = 7; i >= 2; i--) {
			NDEFText = NDEFText.concat("00".substring(Integer.toHexString(
					payload[i] & 0xFF).length())
					+ Integer.toHexString(payload[i] & 0xFF).toUpperCase(
							Locale.getDefault()));

			if (i != 2)
				NDEFText = NDEFText.concat(":");
			else
				NDEFText = NDEFText.concat("\n");
		}

		int fieldLength = 0;
		int fieldPosition = 8;

		do {
			fieldLength = payload[fieldPosition];

			if (payload[fieldPosition + 1] == 0x09) {
				NDEFText = NDEFText.concat("Device Name: ");
				NDEFText = NDEFText.concat(new String(payload,
						fieldPosition + 2, fieldLength) + "\n");
			} else if (payload[fieldPosition + 1] == 0x0D) {
				NDEFText = NDEFText.concat("Service Class: ");
				for (int i = fieldPosition + 4; i >= fieldPosition + 2; i--) {
					NDEFText = NDEFText.concat("00".substring(Integer
							.toHexString(payload[i] & 0xFF).length())
							+ Integer.toHexString(payload[i] & 0xFF)
									.toUpperCase(Locale.getDefault()));

					if (i != fieldPosition + 2)
						NDEFText = NDEFText.concat(":");
					else
						NDEFText = NDEFText.concat("\n");
				}
			}

			fieldPosition = fieldPosition + fieldLength + 1;
		} while (fieldPosition < payload.length);

		return NDEFText;
	}

	/**
	 * This is a mapping of "URI Identifier Codes" to URI string prefixes, per
	 * section 3.2.2 of the NFC Forum URI Record Type Definition document.
	 */
	private static String getUriType(byte uriType) {
		switch (uriType) {
		case 0x01:
			return ("http://www.");
		case 0x02:
			return ("https://www.");
		case 0x03:
			return ("http://");
		case 0x04:
			return ("https://");
		case 0x05:
			return ("tel:");
		case 0x06:
			return ("mailto:");
		case 0x07:
			return ("ftp://anonymous:anonymous@");
		case 0x08:
			return ("ftp://ftp.");
		case 0x09:
			return ("ftps://");
		case 0x0A:
			return ("sftp://");
		case 0x0B:
			return ("smb://");
		case 0x0C:
			return ("nfs://");
		case 0x0D:
			return ("ftp://");
		case 0x0E:
			return ("dav://");
		case 0x0F:
			return ("news:");
		case 0x10:
			return ("telnet://");
		case 0x11:
			return ("imap:");
		case 0x12:
			return ("rtsp://");
		case 0x13:
			return ("urn:");
		case 0x14:
			return ("pop:");
		case 0x15:
			return ("sip:");
		case 0x16:
			return ("sips:");
		case 0x17:
			return ("tftp:");
		case 0x18:
			return ("btspp://");
		case 0x19:
			return ("btl2cap://");
		case 0x1A:
			return ("btgoep://");
		case 0x1B:
			return ("tcpobex://");
		case 0x1C:
			return ("irdaobex://");
		case 0x1D:
			return ("file://");
		case 0x1E:
			return ("urn:epc:id:");
		case 0x1F:
			return ("urn:epc:tag:");
		case 0x20:
			return ("urn:epc:pat:");
		case 0x21:
			return ("urn:epc:raw:");
		case 0x22:
			return ("urn:epc:");
		case 0x23:
			return ("urn:epc:raw:");
		default:
			return "";
		}
	}

	/**
	 * Closes the Reader, Writes the NDEF Message via Android function and
	 * reconnects the Reader
	 * 
	 * @return NDEF Message
	 * @throws IOException
	 * @throws FormatException
	 */
	private void NDEFWrite(NdefMessage msg) throws IOException, FormatException {
		reader.close();
		Ndef ndef = Ndef.get(tag);

		if (ndef != null) {
			ndef.connect();
			ndef.writeNdefMessage(msg);
			ndef.close();
		}
		reader.connect();
	}

	/**
	 * Calculates the Temperature in Celsius
	 * 
	 * @param temp
	 *            Temperature
	 * @return String of Temperature in Dez
	 */
	private String calcTempCelsius(int temp) {
		double Temp_double = 0;
		String Temp_string = "";

		// If the 11 Bit is 1 it is negative
		if ((temp & (1 << 11)) == (1 << 11)) {
			// Mask out the 11 Bit
			temp &= ~(1 << 11);
			Temp_string += "-";
		}

		Temp_double = 0.125 * temp;

		// Update the value on the Led fragment
		LedFragment.setTemperatureC(Temp_double);

		DecimalFormat df = new DecimalFormat("#.00");
		Temp_string = df.format(Temp_double);

		return Temp_string;
	}

	/**
	 * Calculates the Temperature in Farenheit
	 * 
	 * @param temp
	 *            Temperature
	 * @return String of Temperature in Dez
	 */
	private String calcTempFarenheit(int temp) {
		double Temp_double = 0;
		String Temp_string = "";

		// If the 11 Bit is 1 it is negative
		if ((temp & (1 << 11)) == (1 << 11)) {
			// Mask out the 11 Bit
			temp &= ~(1 << 11);
			Temp_string += "-";
		}

		Temp_double = 0.125 * temp;
		Temp_double = 32 + (1.8 * Temp_double);

		LedFragment.setTemperatureF(Temp_double);

		DecimalFormat df = new DecimalFormat("#.00");
		Temp_string = df.format(Temp_double);

		return Temp_string;
	}

	/**
	 * Calculates the Voltage
	 * 
	 * @param volt
	 *            Voltage
	 * @return String Voltage value
	 */
	private String calcVoltage(int volt) {
		String Volt_string = "0.0";

		if (volt > 0) {
			double Volt_double = round((0x3FF * 2.048) / volt);

			// Update the value on the Led fragment
			LedFragment.setVoltage(Volt_double);

			DecimalFormat df = new DecimalFormat("0.0");
			Volt_string = df.format(Volt_double) + "V";
		} else {
			Volt_string = "Not available";
		}
		return Volt_string;
	}

	/*
	 * Rounds the voltage to one single decimal
	 */
	public double round(double value) {
		return Math.rint(value * 10) / 10;
	}

	/*
	 * Helper function to show messages on the screen
	 * 
	 * @param temp Message
	 */
	protected void showResultDialog(String title) {
		new AlertDialog.Builder(main).setTitle(title)
				.setPositiveButton("OK", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
					}
				}).show();
	}

	/*
	 * Helper function to show messages on the screen
	 * 
	 * @param temp Message
	 */
	protected void showResultDialogMessage(String msg) {
		new AlertDialog.Builder(main).setMessage(msg)
				.setPositiveButton("OK", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
					}
				}).show();
	}

	/**
	 * Creates a NDEF Message
	 * 
	 * @param text
	 *            Text to write
	 * @return NDEF Message
	 * @throws UnsupportedEncodingException
	 */
	private NdefMessage createNdefMessage(String text)
			throws UnsupportedEncodingException {
		String lang = "en";
		byte[] textBytes = text.getBytes();
		byte[] langBytes = lang.getBytes("US-ASCII");
		int langLength = langBytes.length;
		int textLength = textBytes.length;
		byte[] payload = new byte[1 + langLength + textLength];
		payload[0] = (byte) langLength;
		System.arraycopy(langBytes, 0, payload, 1, langLength);
		System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength);

		NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
				NdefRecord.RTD_TEXT, new byte[0], payload);

		NdefRecord[] records = { record };
		NdefMessage message = new NdefMessage(records);

		return message;
	}

	protected byte[] concat(byte[] one, byte[] two) {
		if (one == null)
			one = new byte[0];
		if (two == null)
			two = new byte[0];

		byte[] combined = new byte[one.length + two.length];

		System.arraycopy(one, 0, combined, 0, one.length);
		System.arraycopy(two, 0, combined, one.length, two.length);

		return combined;
	}
	
	public void SendData_call(byte[] in,int len)
	{
		mbuffer = in;
		mLen = len;
		ifwrite = true;
		
	}
}
